using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Diagnostics;
using System.Reflection;

using CommonTypes;
using MVCFramework.Models.Controllers;
using BuildingBasicDomain;

using System.Collections.ObjectModel;
using System.Xml;
using System.Resources ;

using System.Diagnostics;
using System.Runtime.InteropServices;

namespace MVCFramework.Models
{
    [CLSCompliant(true)]
    [Serializable ]
    [Obsolete ("Use Decoration with varius functionality decorators ",true )]
    public class Model_Proxy : IModel
    {
        #region Id Members
        private MVCFramework.Id<MVCFramework.IModel> _id;
        public MVCFramework.Id<MVCFramework.IModel> Id
        {
            get
            {
                if (_id.IsEmpty ) return "Model_Proxy";
                return _id;
            }
            set
            {
                _id = value;
            }
        }

        #endregion

        public ResourceManager ModelDataCompositionResources;

        public delegate void GeneralFunction<T>(T _object);
        public delegate bool ActionFunction<T>(T _object);

        private GeneralFunction<object> CheckAdditionRecursive;
        private GeneralFunction<object> CheckRemovalRecursive;

        private ActionFunction<IModelData> RecurseAdditionCallFunction;
        private ActionFunction<IModelData> RecurseRemovalCallFunction;

        #region IModel OGL Members

        [field :NonSerialized ]
        public Hashtable _hashTable;
        public bool needsUpdate = true ;

        public Hashtable HashTable
        {
            get
            {
                return _hashTable;
            }
            set
            {
                log.Info(" Models Needs Update Is set To " + value.ToString());
                _hashTable = value;
            }
        }

        public bool NeedsUpdate
        {
            get
            {
                return needsUpdate;
            }
            set
            {
                needsUpdate = value;
            }
        }

        #endregion

        private static readonly LoggerAdapter log = new LoggerAdapter(typeof(Model_Proxy));

        # region " IEnumerable Implemenation "

		public System.Collections.IEnumerator GetEnumerator()
		{
          // foreach (IList<IModelData> modeldata in _model)
            foreach (IModelData data in _model)
                { yield return data; }
        }

        # endregion

        #region "Controllers implementation"

        public IController AdditionController;
        public IController RemovalController;
        public Controller basecontroller;

        #endregion

        # region Events Decleration "
        [field:NonSerialized ]
        public event EventHandler<PersistEventArgs> OnDataValueChanged;
        [field: NonSerialized]
        public event EventHandler<ModelModificationEventArgs> OnAddElement;
        [field: NonSerialized]
        public event EventHandler<ModelModificationEventArgs> OnRemoveElement;
        [field: NonSerialized]
        public event EventHandler<ModelModificationEventArgs> OnGetElement;

        #endregion

        protected  Model _model;

        public object _objectInProcess;
        public bool ListNotificationIsEnabled;

        public Model_Proxy()
        {
            ModelInitializtion();
        }
        public Model_Proxy(string id)
        {
            Id = id;
            ModelInitializtion();
            
        }
        public Model_Proxy(Model model):this()
        {
            log.Warn(" Models" + this.Id + "  Initailization With Existing Models " + model.ToString());

            this._model = model;
        }

        private void ModelInitializtion()
        {
            log.Info(" Models  " + this.Id + " Inisialization");

            WireUpModel();
            ListNotificationIsEnabled = true;
            DoAdditionalInitializations();

            basecontroller = new Controller(_model);
            basecontroller.id = "Base";

            WireUpControllers();

            DoWireUpDeepAddition();
            log.Info(" Models " + this.Id + " Inisialization Finished ");
        }

        protected virtual void DoWireUpDeepAddition()
        {
            this.CheckAdditionRecursive = CheckModelDeepAddition;//CheckModelDeepAddition  ;
            this.CheckRemovalRecursive = CheckModelDeepRemoval;

            RecurseAdditionCallFunction =  RecursionEntryPointAdd ;
            RecurseRemovalCallFunction = RecursionEntryPointRemove ;
        }

        protected virtual void DoAdditionalInitializations()
        {
            
        }

        protected virtual void WireUpModel()
        {
            this._model = new Model();
        }

        protected virtual void WireUpControllers()
        {
            log.Info("Models" + this.Id + "  Controllers Inisialization");

            //Controller compositionController = new CompositionController(this);


            log.Info("Models " + this.Id + " Controllers Xml Configuration started ");
            try
            {
                XmlControllerConfigurator.Configure(this, Assembly.GetAssembly(typeof(Model_Proxy )), typeof(Model_Proxy), "XmlControllersConfigurator.xml");
            }
            catch
            {
                Trace.TraceWarning("Model_Proxy Geometry Controllers failed to  be Configured by Xml");
                log.Warn ("Model_Proxy Geometry Controllers failed to  be Configured by Xml"); 
            }

            log.Info("Models Controllers Inisialization Finished ");


        }

        # region " Modify Models Decleration "

        public virtual bool AddObject(IModelData  _object)
        {    
            if (DoCheckIfObjectExistToModel(_object)) return false;
            _objectInProcess = _object;

            return RecursionEntryPointAdd(_object);
        }

        private bool RecursionEntryPointAdd(IModelData _object)
        {

            log.Info("Models" + this.Id + "  Object Addtion " + _object.ToString());
            Debug.Assert(_object != null);
            try
            {
                DoDeActivateControllers(_object);
                CheckAdditionRecursive(_object);
                DoActivateControllers(_object);

                bool validation = AdditionController.CheckAddition( _object);
                if (validation == true)
                {
                    if (OnAddElement != null)
                        OnAddElement(this, new ModelModificationEventArgs(_object, ModelChangeType.Added));
                    needsUpdate = true;
                    log.Info("Added to Models " + _object.ToString());
                }
                else
                {
                    log.Warn (_object + " was  not Added To Models ");
                    Trace.TraceWarning(_object + " was  not Addet To Models ");
                }
                return validation;

            }
            catch (Exception e)
            {
                Trace.TraceError ("Exeption raised  " + e.ToString() + "in model _proxy addition ");
                log.Error ("Exeption raised  " + "in model _proxy addition ",e);
                throw new ModelExeption("Object " + _object.ToString() + " Cannot be added to model", e);
            }
        }

        protected virtual bool DoCheckIfObjectExistToModel(IModelData _object)
        {
            if (_model.Contains(_object)) return true;
            else return false;
        }

        protected virtual void DoActivateControllers(IModelData _object)
        {
            
        }

        protected virtual  void DoDeActivateControllers(IModelData _object)
        {
            
        }

        [Obsolete ("Not Used",true )]
        private void CheckPersistanceAdditionDeep(object _object )
        {
            if (_object is IPersistant)
                (_object as IPersistant).OnModify += new EventHandler<PersistEventArgs>(Model_Proxy_OnModify);
        }
        [Obsolete("Not Used", true)]
        void Model_Proxy_OnModify(object sender, PersistEventArgs e)
        {
            if (OnDataValueChanged != null)
                OnDataValueChanged(sender, e);
        }

        public virtual bool RemoveObject(IModelData _object)
        {
            return RecursionEntryPointRemove(_object);
        }

        private bool RecursionEntryPointRemove(IModelData _object)
        {
            log.Info("Models" + this.Id + "  Object Removal " + _object.ToString());
            Debug.Assert(_object != null);
            try
            {
                CheckRemovalRecursive(_object);

                bool validation = RemovalController.CheckRemoval(_object);
                if (validation == true)
                {
                    log.Info("Removed from Models " + _object.ToString());
                    if (OnRemoveElement != null)
                        OnRemoveElement(this, new ModelModificationEventArgs(_object, ModelChangeType.Removed));
                    needsUpdate = true;
                }
                else
                {
                    log.Warn(_object + " was  not Removed from Models ");
                    Trace.TraceWarning(_object + " was  not Removed from Models ");
                }
                return validation;

            }
            catch (Exception e)
            {
                Trace.TraceWarning("Exeption raised  " + e.ToString() + "in model _proxy Removal ");
                log.Warn("Exeption raised  " + e.ToString() + "in model _proxy removal ");
                throw new ModelExeption("Object " + _object.ToString() + " Cannot be Removed from model", e);
            }
        }
        
        private void CheckPersistanceRemovalDeep()
        {

        }

        # region "Container Collection Handling Block"

        #region  " "
        [Obsolete("Deep Addition is Used instead",true )]
        private void CheckModelAdditionContainer(IModelData _object)
        {
            foreach (PropertyInfo property in _object.GetType().GetProperties())
            {
                if (property.IsDefined(typeof(ModelContainmentAttribute), false))
                {
                    MethodInfo getinfo = property.GetGetMethod(true);
                    object[] aa = new object[0];
                    object _returnObject = getinfo.Invoke(_object, aa);
                    if (_returnObject is IList)
                    {
                        foreach (object data in (_returnObject as IList))
                            if (data is IModelData)
                                this.AddObject(data as IModelData);
                    }
                    else
                        if (_returnObject is IModelData)
                            this.AddObject(_returnObject as IModelData);
                }

            }
        }
        [Obsolete("Deep Removal is Used instead",true )]
        private void CheckModelRemovalContainer(IModelData _object)
        {
            foreach (PropertyInfo property in _object.GetType().GetProperties())
            {
                if (property.IsDefined(typeof(ModelContainmentAttribute), false))
                {
                    MethodInfo getinfo = property.GetGetMethod(true);
                    object[] aa = new object[0];
                    object _returnObject = getinfo.Invoke(_object, aa);
                    if (_returnObject is IList)
                    {
                        foreach (object data in (_returnObject as IList))
                            if (data is IModelData)
                                this.RemoveObject(data as IModelData);
                    }
                    else
                        if (_returnObject is IModelData)
                            this.RemoveObject(_returnObject as IModelData);
                }

            }
        }
        #endregion 

        # region "Attribute Configuration for Deep Composition"

        private IDictionary<Type, bool> SimpleCache = new Dictionary<Type, bool>();

        private void CheckModelDeepAddition(object _object)
        {
            //Debug.Assert(_object != null);

            if (_object == null) return;

            if (SimpleCache.ContainsKey (_object.GetType()))
            {
                if (SimpleCache[_object.GetType()] == true)
                    ProccesAdddition(_object);
            }
            else
            {
                # region Check For  Type and add
                if (_object.GetType().IsDefined(typeof(ModelContainmentAttribute), false))
                {
                    object[] atrribute = _object.GetType().GetCustomAttributes(typeof(ModelContainmentAttribute), false);
                    bool inheritance = (atrribute[0] as ModelContainmentAttribute).CheckDeepContainment;
                    IList<IController> _controllersDeactivate = (atrribute[0] as ModelContainmentAttribute)._controllers ;

                    SimpleCache.Add(_object.GetType(), inheritance);
                    if (inheritance == true)
                        ProccesAdddition(_object);
                }
                #endregion
            }
            
                  
        }
        private void ProccesAdddition(object _object)
        {

            PropertyInfo[] properties = _object.GetType().GetProperties();
            foreach (PropertyInfo property in properties)
            {
                if (property.IsDefined(typeof(ModelContainmentAttribute), true))
                {
                    log.Info("Propery " + property.ToString() + "Is Examining for Models Addition");
                    MethodInfo getinfo = property.GetGetMethod(true);
                    object[] aa = new object[0];
                    object _returnObject = getinfo.Invoke(_object, aa);
                    if (_returnObject is IList)
                    {
                        log.Info(" List Is Checked for DeepComposition " + _returnObject.ToString());
                        foreach (object data in (_returnObject as IList))
                        {
                            log.Info("data " + data.ToString() + " Is Examining");
                            if (data is IModelData)
                                this.RecurseAdditionCallFunction(data as IModelData);
                        }
                        if (_returnObject is IDomainCollection)
                            RegisterCollectionEventHandler(_returnObject as IDomainCollection);
                    }
                    else if (_returnObject is IModelData)
                        this.RecurseAdditionCallFunction(_returnObject as IModelData);
                    else
                    {
                        log.Info(" Recursive call to DeepAddition  ");
                        CheckModelDeepAddition(_returnObject);
                    }
                }

            }
        }

        private void CheckModelDeepRemoval(object _object)
        {
            // Debug.Assert(_object != null);
            if (_object == null) return;

            if (SimpleCache.ContainsKey(_object.GetType()))
            {
                if (SimpleCache[_object.GetType()] == true)
                    ProccesRemoval(_object);
            }
            else
            {
                # region Check For  Type and add
                if (_object.GetType().IsDefined(typeof(ModelContainmentAttribute), false))
                {
                    object[] atrribute = _object.GetType().GetCustomAttributes(typeof(ModelContainmentAttribute), false);
                    bool inheritance = (atrribute[0] as ModelContainmentAttribute).CheckDeepContainment;

                    SimpleCache.Add(_object.GetType(), inheritance);
                    if (inheritance == true)
                        ProccesRemoval(_object);
                }
                #endregion
                /* * */
            }
        }

        private void ProccesRemoval(object _object)
        {

            foreach (PropertyInfo property in _object.GetType().GetProperties())
            {
                if (property.IsDefined(typeof(ModelContainmentAttribute), true))
                {
                    MethodInfo getinfo = property.GetGetMethod(true);
                    object[] aa = new object[0];
                    object _returnObject = getinfo.Invoke(_object, aa);
                    if (_returnObject is IList)
                    {
                        ListModificationMethod(_returnObject as IList);
                    }
                    else if (_returnObject is IModelData)
                        RecurseRemovalCallFunction(_returnObject as IModelData);
                    else
                    {
                        log.Info("Recursive Call to DeepRemoval");

                        CheckModelDeepRemoval(_returnObject);
                    }
                }

            }
        }

        private void ListModificationMethod(IList list)
        {

            log.Info(" List Is Checked for DeepComposition Removal" + list.ToString());

            if (list is IDomainCollection)
            {
                if (((IDomainCollection)list).IsModelModifiededCollection)
                {
                    IDomainCollection _returnObject = list as IDomainCollection;

                    object _firsObjectInCollection;

                    while ((_returnObject).Count != 0)
                    {
                        _firsObjectInCollection = (_returnObject as IList)[0];

                        log.Info("data " + _firsObjectInCollection.ToString() + " Is Examining For Removal");
                        if (_firsObjectInCollection is IModelData)
                            RecurseRemovalCallFunction(_firsObjectInCollection as IModelData);
                    }
                }
                else
                    IterateListAndRemove(list);

                UnRegisterCollectionEventHandler(list as IDomainCollection);
            }
            else
                IterateListAndRemove(list);


        }
        private void IterateListAndRemove(IList list)
        {
            foreach (object _object in list)
            {
                log.Info("data " + _object.ToString() + " Is Examining For Removal");
                if (_object is IModelData)
                    RecurseRemovalCallFunction(_object as IModelData);
            }
        }

        #endregion

        # region "XmlConfiguration for Deep Composition"

        private GeneralFunction<object> GetCopositeDataCalculationFunction(GeneralFunction<object> recurse, ActionFunction<IModelData> modificationFunction, GeneralFunction<IDomainCollection> registrationFunction)
        {
            return delegate(object _object) {
                if (_object == null) return;

                string _objectName = _object.GetType().Name;
                string XmlResource = ModelDataCompositionResources.GetString(_objectName);

                if (XmlResource != "" && XmlResource != null)
                {
                    XmlReader reader = XmlReader.Create(new System.IO.StringReader(XmlResource));
                    while (reader.Read())
                    {
                        if (reader.NodeType == XmlNodeType.Text)
                        {

                            string PropertyNameToInvoke = reader.Value;
                            if (PropertyNameToInvoke != "")
                            {
                                # region " Main Logic"

                                PropertyInfo property = _object.GetType().GetProperty(PropertyNameToInvoke);

                                MethodInfo getinfo = property.GetGetMethod(true);
                                object[] aa = new object[0];
                                object _returnObject = getinfo.Invoke(_object, aa);
                                if (_returnObject is IList)
                                {
                                    foreach (object data in (_returnObject as IList))
                                        if (data is IModelData)
                                            this.AddObject(data as IModelData);
                                    if (_returnObject is IDomainCollection)
                                        registrationFunction(_returnObject as IDomainCollection);
                                }
                                else if (_returnObject is IModelData)
                                    modificationFunction(_returnObject as IModelData);
                                else
                                    recurse(_returnObject);

                                #endregion
                            }
                        }
                    }

                }
            };
        }

        private void CheckXmlDeepAddition(object _object)
        {
            if (_object == null) return;

            string _objectName = _object.GetType().Name;
            string XmlResource = ModelDataCompositionResources.GetString(_objectName);

            if (XmlResource != "" && XmlResource !=null)
            {

                XmlReader reader = XmlReader.Create(new System.IO.StringReader(XmlResource));
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Text)
                    {

                        string PropertyNameToInvoke = reader.Value;
                        if (PropertyNameToInvoke != "")
                        {
                            # region " Main Logic"

                            PropertyInfo property = _object.GetType().GetProperty(PropertyNameToInvoke);

                            MethodInfo getinfo = property.GetGetMethod(true);
                            object[] aa = new object[0];
                            object _returnObject = getinfo.Invoke(_object, aa);
                            if (_returnObject is IList)
                            {
                                foreach (object data in (_returnObject as IList))
                                    if (data is IModelData)
                                        this.AddObject(data as IModelData);
                                if (_returnObject is IDomainCollection)
                                    RegisterCollectionEventHandler(_returnObject as IDomainCollection);
                            }
                            else if (_returnObject is IModelData)
                                this.AddObject(_returnObject as IModelData);
                            else
                                CheckXmlDeepAddition(_returnObject);
    
                            #endregion
                        }
                    }
                }
                
            }
            
        }
        private void CheckXmlDeepRemoval(object _object)
        {
            if (_object == null) return;

            string _objectName = _object.GetType().Name;
            string XmlResource = ModelDataCompositionResources.GetString(_objectName);

            if (XmlResource != "" && XmlResource != null)
            {

                XmlReader reader = XmlReader.Create(new System.IO.StringReader(XmlResource));
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Text)
                    {

                        string PropertyNameToInvoke = reader.Value;
                        if (PropertyNameToInvoke != "")
                        {
                            # region " Main Logic"

                            PropertyInfo property = _object.GetType().GetProperty(PropertyNameToInvoke);

                            MethodInfo getinfo = property.GetGetMethod(true);
                            object[] aa = new object[0];
                            object _returnObject = getinfo.Invoke(_object, aa);
                            if (_returnObject is IList)
                            {
                                foreach (object data in (_returnObject as IList))
                                    if (data is IModelData)
                                        this.RemoveObject (data as IModelData);
                                if (_returnObject is IDomainCollection)
                                    UnRegisterCollectionEventHandler (_returnObject as IDomainCollection);
                            }
                            else if (_returnObject is IModelData)
                                this.RemoveObject(_returnObject as IModelData);
                            else
                                CheckXmlDeepRemoval(_returnObject);

                            #endregion
                        }
                    }
                }

            }

        }

        #endregion

        private void RegisterCollectionEventHandler(IDomainCollection  _returnObject)
        {
            Debug.Assert(_returnObject != null);
            log.Info(_returnObject.ToString() + "registered to model ");

            _returnObject.OnChange += new EventHandler<DomainCollectionChangedEventArgs<object>>(CollectionChangedHandler);
            OnRemoveElement += new EventHandler<ModelModificationEventArgs>(_returnObject.ModelModifiedCollectionHandler);
        }
        private void UnRegisterCollectionEventHandler(IDomainCollection _returnObject)
        {
            Debug.Assert(_returnObject != null);
            log.Info(_returnObject.ToString() + "Remove registeration to model ");
            _returnObject.OnChange -= new EventHandler<DomainCollectionChangedEventArgs<object>>(CollectionChangedHandler);
            OnRemoveElement -= new EventHandler<ModelModificationEventArgs>(_returnObject.ModelModifiedCollectionHandler);
        }

        public void CollectionChangedHandler(object sender, DomainCollectionChangedEventArgs<object> Args)
        {
            if (!ListNotificationIsEnabled) return;

            System.Diagnostics.Debug.Assert(sender != null);
            if (Args.ChangeType == ChangeType.Added && Args.ChangedItem is IModelData)
                AddObject(Args.ChangedItem as IModelData);
            if (Args.ChangeType == ChangeType.Removed && Args.ChangedItem is IModelData)
                RemoveObject(Args.ChangedItem as IModelData);
            if (Args.ChangeType == ChangeType.Cleared)
            {
                foreach (object _object in Args.items)
                    RemoveObject(_object as IModelData);
            }
        }

        # endregion

        public object GetObject(int id)
        {
            return _model.GetObject(id);
        }

        public IList<IModelData> GetGroup(string name)
        {
            return _model.GetGroup(name);
        }

        [Obsolete ("Indexer is Used Instead ",true )]
        public virtual IList<IModelData> GetGroup(Type type)
        {
            return new ReadOnlyCollection <IModelData > (  _model.GetGroup(type));
        }

        public bool ContainsGroup(String name)
        {
            return  _model.ContainsGroup(name);
        }

        public bool Contains(IModelData _object)
        {
           return  _model.Contains(_object);
        }

        public bool Modify(IModelData _object, Vector v)
        {
            return _model.Modify(_object, v);
        }

        # endregion 

        # region "IVisitorhost Implementation "

        public void Accept(IVisitor visitor)
        {
            visitor.Visit(this);
        }

        # endregion

        #region IModel Members

        [Obsolete ("Use Type Indexer ",false)]
        public virtual IList<IModelData> this[string name]
        {
            get
            {
                IList<IModelData> data = _model[name];
                if (data != null)
                    return new ReadOnlyCollection<IModelData>(data);
                else return null;
            }
        }

        public virtual IList<IModelData> this[Type type]
        {
            get
            {
                IList<IModelData> data = _model[type];
                if (data != null)
                    return new ReadOnlyCollection<IModelData>(data);
                else return null;
            }
        }

        #endregion

        #region IModelExplicit Members

       public  void AttachEventHandlerToData(object attribute, EventHandler _eventHandler)
        {
            _model.AttachEventHandlerToData(attribute, _eventHandler);
        }

        public void DettachEventHandlerToData(object attribute, EventHandler EventHandler)
        {
            _model.DettachEventHandlerToData(attribute, EventHandler);
        }

        public T GetObject<T>(object name)
        {
           return  _model.GetObject<T>(name);
        }

        public void SetObject(object name, object _object)
        {
            _model.SetObject(name, _object);
        }

        public object this[object Name]
        {
            get
            {
               return  _model.GetObject<object>(Name);
            }
            set
            {
                _model.SetObject(Name, value);
            }
        }

        #endregion

        #region IModel Members

        public int MaxId
        {
            get { return _model.MaxId ;}
        }

        #endregion

        public void Serialize(string p)
        {
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

            System.IO.Stream stream = new System.IO.FileStream(p, System.IO.FileMode.Create, System.IO.FileAccess.Write,System.IO .FileShare .None );
         //   formatter.Serialize(stream, this._model);
            stream.Close();

         //   stream = System.IO.File.OpenRead(p);
         //   MVCFramework.Models.Model loadedmodel = (MVCFramework.Models.Model )formatter.Deserialize(stream);

        }

        public void DeSerialize(string p)
        {
            System.IO.Stream  stream = System.IO.File.OpenRead(p);
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            MVCFramework.Models.Model loadedmodel = (MVCFramework.Models.Model)formatter.Deserialize(stream);
            this._model = loadedmodel;
        }

        #region IModel Members

        public object DeepCopy()
        {
            return _model.DeepCopy();
        }

        #endregion

        #region IModel Members

        public void RequestIdRegistration(object _object)
        {
            _model.RequestIdRegistration(_object);
        }

        #endregion

        #region IModelExplicit Members


        T IModelExplicit.GetObject<T>(object name)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public void SetObject(object name, object _object, bool addToData)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion
    }

    [CommonTypes .PerformanceCounterCategory ("MVCFrameWorkModelCounter","Counts Performance of Model Addition - Removal Procces",PerformanceCounterCategoryType .MultiInstance )]
    public class ModelPerformanceCounter
    {
        /// <summary>
        /// Imports the <code>QueryPerformanceFrequency</code> method into the class. The method is used to measure the current
        /// tickcount of the system.
        /// </summary>
        /// <param name="ticks">current tick count</param>
        [DllImport("Kernel32.dll")]
        public static extern void QueryPerformanceCounter(ref long ticks);

        /// <summary>
        /// Counter for counting total number of operations
        /// </summary>
        [CommonTypes.PerformanceCounter("Total Operations", PerformanceCounterType.NumberOfItems32)]
        private PerformanceCounter _TotalOperations;
        /// <summary>
        /// Counter for counting number of operations per second
        /// </summary>
        [CommonTypes.PerformanceCounter("# OperationsAdd/Sec",PerformanceCounterType. RateOfCountsPerSecond32)]
        private PerformanceCounter _OperationsAddPerSecond;
        /// <summary>
        /// Counter for counting duration averages
        /// </summary>
        [CommonTypes.PerformanceCounter("Average Duration", PerformanceCounterType.AverageTimer32)]
        private PerformanceCounter _AverageDuration;

        /// <summary>
        /// Counter for counting number of operations per second
        /// </summary>
        [CommonTypes.PerformanceCounter("# OperationsRemove/Sec", PerformanceCounterType.RateOfCountsPerSecond32)]
        private PerformanceCounter _OperationsRemovePerSecond;

        /// <summary>
        /// Creates a new performance counter category "MyCategory" if it does not already exists and adds some counters to it.
        /// </summary>
        /// 
        CommonTypes.PerformanceCounterFactory factory;
        public ModelPerformanceCounter()
        {
            factory = new PerformanceCounterFactory(typeof(ModelPerformanceCounter));         
            CommonTypes.PerformanceCounterFactory.CreateCounters(typeof(ModelPerformanceCounter), this);
        }

        /// <summary>
        /// Increments counters.
        /// </summary>
        /// <param name="ticks">The number of ticks the AverageTimer32 counter must be incremented by</param>
        public void DoSomeProcessingAdd(long ticks)
        {
                        
            // simply increment the counters
            _TotalOperations.Increment();          
            _OperationsAddPerSecond . Increment();
            _AverageDuration.IncrementBy(ticks); // increment the timer by the time cost of the operation
         //   _AverageDurationBase.Increment(); // increment base counter only by 1
        }
        public void DoSomeProcessingRemove(long ticks)
        {

            // simply increment the counters
            _TotalOperations.Increment();
            _OperationsRemovePerSecond . Increment();
            _AverageDuration.IncrementBy(ticks); // increment the timer by the time cost of the operation
            //   _AverageDurationBase.Increment(); // increment base counter only by 1
        }
        public void ClearTotalProccesses()
        { _TotalOperations.RawValue = 0; } 
    }

    [CLSCompliant(true)]
    [Serializable]
    public class Model_Proxy2 : ModelDecorator 
    {
        # region Preformnace Counters
        [NonSerialized ]
        private  ModelPerformanceCounter PerformanceCounter ;
 
        # endregion 

        private readonly LoggerAdapter log = new LoggerAdapter(typeof(IModel));
        
        public Model_Proxy2(IModel model,string id):base ( model ) 
        {
            try
            {
                Id = id;
                ModelInitializtion();
            }
            catch
            {
                Trace.TraceError("Exeption raised in Model_Proxy  Initialization ");
                throw new ModelExeption(" Model_Proxy Falied To Initialize "); 
            }
           
        }
        public Model_Proxy2(IModel model):base ( model)
        {

          //  log.Warn(" Models" + this.Id + "  Initailization With Existing Models " + model.ToString());
            ModelInitializtion();
        }

        private void ModelInitializtion()
        {
            log.Info(" Models  " + this.Id + " Inisialization");

            DoAdditionalInitializations();

            log.Info(" Models " + this.Id + " Inisialization Finished ");
        }
        protected virtual void DoAdditionalInitializations()
        {
            PerformanceCounter = new ModelPerformanceCounter();
        }

        public override bool AddObject(IModelData _object)
        {
          //  log.Info("Models" + this.Id + "  Object Addtion " + _object.ToString());
            Debug.Assert(_object != null);
            try
            {
                long startTime = 0;
                long endTime = 0;
                ModelPerformanceCounter.QueryPerformanceCounter(ref startTime);

                bool validation = Model.AddObject(_object);

                ModelPerformanceCounter.QueryPerformanceCounter(ref endTime);

                PerformanceCounter.DoSomeProcessingAdd(endTime - startTime);
                PerformanceCounter.ClearTotalProccesses();


                if (validation == true)
                {
                    RaiseAddObjectEvent(_object);
                    needsUpdate = true;
                    log.Info("Added to Models " + _object.ToString());
                }
                else
                {
                    log.Warn(_object + " was  not Added To Models ");
                    Trace.TraceWarning(_object + " was  not Addet To Models ");
                }
                return validation;

            }
    
            catch (Exception e)
            {
                Trace.TraceError("Exeption raised  " + e.ToString() + "in model _proxy addition ");
                log.Error("Exeption raised  " + "in model _proxy addition ", e);
                throw new ModelExeption("Object " + _object.ToString() + " Cannot be added to model", e);
            }

        }

        protected virtual bool DoCheckIfObjectExistToModel(IModelData _object)
        {
            if (Model.Contains(_object)) return true;
            else return false;
        }

        public override bool RemoveObject(IModelData _object)
        {
            log.Info("Models" + this.Id + "  Object Removal " + _object.ToString());
            Debug.Assert(_object != null);
            try
            {
                long startTime = 0;
                long endTime = 0;
                ModelPerformanceCounter.QueryPerformanceCounter(ref startTime);

                bool validation =  Model .RemoveObject (_object);
                // measure ending time
                ModelPerformanceCounter.QueryPerformanceCounter(ref endTime);

                PerformanceCounter.DoSomeProcessingRemove(endTime - startTime);
                if (validation == true)
                {
                    log.Info("Removed from Models " + _object.ToString());
                    RaiseRemoveObjectEvent(_object);
                    needsUpdate = true;
                }
                else
                {
                    log.Warn(_object + " was  not Removed from Models ");
                    Trace.TraceWarning(_object + " was  not Removed from Models ");
                }
                return validation;

            }
            catch (Exception e)
            {
                Trace.TraceWarning("Exeption raised  " + e.ToString() + "in model _proxy Removal ");
                log.Warn("Exeption raised  " + e.ToString() + "in model _proxy removal ");
                throw new ModelExeption("Object " + _object.ToString() + " Cannot be Removed from model", e);
            }
        }

        #region IModel Members

        [Obsolete("Use Type Indexer ", false)]
        public override IList<IModelData> this[string name]
        {
            get
            {
                IList<IModelData> data = Model [name];
                if (data != null)
                    return new ReadOnlyCollection<IModelData>(data);
                else return null;
            }
        }

        public override  IList<IModelData> this[Type type]
        {
            get
            {
                IList<IModelData> data = Model[type];
                if (data != null)
                    return new ReadOnlyCollection<IModelData>(data);
                else return null;
            }
        }

        #endregion

        public void Serialize(string p)
        {
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

            System.IO.Stream stream = new System.IO.FileStream(p, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None);
            //   formatter.Serialize(stream, this._model);
            stream.Close();

            //   stream = System.IO.File.OpenRead(p);
            //   MVCFramework.Models.Model loadedmodel = (MVCFramework.Models.Model )formatter.Deserialize(stream);

        }

        public void DeSerialize(string p)
        {
            System.IO.Stream stream = System.IO.File.OpenRead(p);
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            MVCFramework.Models.Model loadedmodel = (MVCFramework.Models.Model)formatter.Deserialize(stream);
            this.Model = loadedmodel;
        }

    }
}
